# coding=utf-8
import cv2
import numpy as np
import serial
import time

# 创建串行端口连接
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)  #ttyUSB0  ttyACM0
ser.write(f"G28\n".encode())

# 现实3D坐标
fact_x, fact_y, fact_z = 0, 0, 0
# 摄像头坐标
mouse_x, mouse_y = 0, 0
# 鼠标左键点击移动差
l_delta_x, l_delta_y = 0, 0
# 鼠标左键点击标志位
l_down_fla = False
# 鼠标中键点击标志位
m_down_fla = False

# 鼠标回调函数
def Mouse_Callback(event, x, y, flags, param):
    # 左右键输出提示与键值，其余按键事件就不例举了，直接打印定义的键值了
    if event == cv2.EVENT_LBUTTONDOWN:
        print("L_Button Down {}\r\n".format(event))
    elif event == cv2.EVENT_RBUTTONDOWN:
        print("R_Button Down {}\r\n".format(event))
    else:
        print(event)

    """
        # 鼠标拖动画面
        global fact_x, fact_y, mouse_x, mouse_y, l_delta_x, l_delta_y, l_down_fla
        if event == cv2.EVENT_LBUTTONDOWN and l_down_fla == False:
            print("L_Button Down")
            mouse_x, mouse_y = x, y
            l_down_fla = True    
        elif event == cv2.EVENT_LBUTTONUP:
            print("L_Button Up")  
            l_down_fla = False
        elif l_down_fla == True:
            l_delta_x, l_delta_y = x - mouse_x, y - mouse_y
            fact_x, fact_y = fact_x + l_delta_x/2600*10, fact_y + l_delta_y/1940*10
            fact_x, fact_y = min(max(fact_x, 0), 180), min(max(fact_y, 0), 180)
            ser.write(f"G1 X{int(fact_y)} Y{int(fact_x)} F2000\n".encode())
    """
    
    # 调整摄像头高度
    global fact_z, m_down_fla
    if event == cv2.EVENT_MBUTTONDOWN:
        m_down_fla = not m_down_fla
    if m_down_fla and flags == -7864318:
        fact_z = fact_z + 1
    elif m_down_fla and flags == 7864322:
        fact_z = fact_z - 1
    fact_z = min(max(fact_z, 0), 180)
    ser.write(f"G1 Z{int(fact_z)} F1000\n".encode())

    # 鼠标点击画面
    global mouse_x, mouse_y, fact_x, fact_y
    if event == cv2.EVENT_LBUTTONDOWN:
        mouse_x, mouse_y = x, y
        fact_x, fact_y = fact_x + (0.5-mouse_x/1920)*(fact_z*1.9+23),fact_y + (0.5-mouse_y/1080)*(fact_z*1.2+13)  
        ser.write(f"G1 X{int(fact_y)} Y{int(fact_x)} F2000\n".encode())     

    # 输出鼠标坐标\Flags\userdata
    print("Mouse position :  X :" + str(x) + " Y :" + str(y) + "\r\n")
    print("Fact position :  X :" + str(int(fact_y)) + " Y :" + str(int(fact_x)) + " Z :" + str(int(fact_z)) + "\r\n")
    print("Flags : {}".format(flags))
    print(f"Userdata is{param}\r\n\r\n")

# 打开摄像头
cap = cv2.VideoCapture(0)  # 0代表默认摄像头
if not cap.isOpened():
    print("无法打开摄像头")
    exit()

# 创建窗口
cv2.namedWindow("mouse", cv2.WINDOW_NORMAL)
cv2.resizeWindow("mouse", 1280, 640)

# 设置鼠标回调
cv2.setMouseCallback("mouse", Mouse_Callback)

while True:
    # 捕获摄像头的一帧
    ret, frame = cap.read()
    if not ret:
        print("无法读取帧")
        break

    # 显示窗口与背景
    cv2.imshow("mouse", frame)

    # 检查是否按下了'q'键
    key = cv2.waitKey(1)
    if key & 0xFF == ord('q'):
        break

# 释放所有资源
cap.release()
cv2.destroyAllWindows()
ser.close()